
#include "Spi.h"

#include <stdio.h>
//uncomment to do testing
//#define TEST_SPI


Spi::Spi()
{
	start = 0;
	transferCount = 0;
	CPOL = 0;
	CPHA = 0;
}

Spi::Spi(BitPointer sel, Clock clk, BitPointer in, BitPointer out,
			unsigned char polarity, unsigned char phase, unsigned char master)
{
	start = 0;
	transferCount = 0;
	slaveOrMaster = master;
	SS = sel;
	SCK = clk;
	MISO = BitShifter(0, in);
	MOSI = BitShifter(0, out);
	
	//set fill values to 1
	MISO.setFill(1);
	MOSI.setFill(1);
	//set the watcher now
	watcher = EdgeWatcher(SCK.getPointer(), SCK.getPeriod());
	
	CPOL = polarity;
	CPHA = phase;
	if(slaveOrMaster == 1)
		SCK.setMonitor(0);
	else
		SCK.setMonitor(1);

	SCK.setValue(polarity);
	//set the initial clock correctly.
}

void Spi::sendBit()
{

	if(slaveOrMaster==0) //it is the slave sending data out //use MISO
		MISO.shiftIn();
	else //use MOSI
		MOSI.shiftIn();
}

void Spi::receiveBit()
{
	//now to do the reverse
	if(slaveOrMaster==0) //it is the slave taking data in //use MOSI
		MOSI.shiftOut();
	else //use MISO
		MISO.shiftOut();
}

void Spi::sampleBit()
{
	//sample the wave form
	sendBit();
	receiveBit(); //this MUST be second.

	//increment transfer count
	transferCount = transferCount + 1;
}

void Spi::setInput(unsigned char value)
{
	if(slaveOrMaster==0) //it is the slave sending data out //use MISO
		MISO.setValue(value);
	else //use MOSI
		MOSI.setValue(value);
}

unsigned char Spi::getInput() //used mainly for testing purposes.
{
	if(slaveOrMaster==0) //it is the slave sending data out //use MISO
		return MISO.getValue();
	else //use MOSI
		return MOSI.getValue();
}

void Spi::select()
{
	if(slaveOrMaster==1)//only master can do the select operation.
		SS.setBit(1);
}

void Spi::deselect()
{
	if(slaveOrMaster==1)//only master can do the select operation.
		SS.setBit(0);
}

unsigned char Spi::getOutput()
{
	//now to do the reverse
	if(slaveOrMaster==0) //it is the slave taking data in //use MOSI
		MOSI.getValue();
	else //use MISO
		MISO.getValue();
}


void Spi::run()  /////assumes that I don't deselect when finished left up to the user.
{
	//ss is independent of actual process.
	//if(getPointerValue(&(spi->SS))==1)//transfers have started now.
	//{

		SCK.run();
		//run the watcher after the clock
		watcher.run();
		//after running the clock check a few things
		if(CPOL==0)
		{

			if(watcher.risingEdge()==1 
				&& CPHA== 0) //rising edge ODD sampling
			{	
				sampleBit();
			}
			else if(watcher.fallingEdge()==1 
				&& CPHA == 1)//falling edge even sampling		
			{
				sampleBit();
			}
		}
		else //cpol == 1
		{
			if(watcher.risingEdge()==1 
				&& CPHA == 1) //even case
			{	
				sampleBit();
			}
			else if(watcher.fallingEdge()==1 
				&& CPHA == 0) //odd case
			{	
				sampleBit();
			}
		}
		//now check if I'm done doing the transfer now.
		if(transferCount >= 8)
		{
			//reset the transfer
			transferCount = 0;
			//don't need to do anything here just note you finished all transfers.
		}
	//}
	//do nothing otherwise.

}



